package slw.display
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	
	import slw.core.UIComponent;
	import slw.core.UISprite;
	import slw.utils.Base64;
	import slw.utils.BitmapDataEncoder;
	
	
	/**
	 * SimulateMovieClip
	 * 模拟影片剪辑MovieClip功能的类,数据为2维数组，每帧对应1个数组，帧数组中的数据将全部以显示对象显示在当前帧，
	 * 支持显示对象数组和位图数据数组(用BitmapDataEncoder和Base64将BitmapData编码为字符串数组)
	 * @author ddx<br/>
	 * 2011-7-1
	 *
	 */
	public class SimulateMovieClip extends UISprite
	{
		//帧数组(显示对象数据数组)
		private var _datas:Array=[];
		//影片帧频
		private var _fps:uint=24;
		//计时器
		private var _playTimer:Timer;
		//是否正在播放
		private var _isPlaying:Boolean=false;
		//当前帧
		private var _currentFrame:int=0;
		/**
		 * 构造函数 
		 * @param datas:Array=null 帧数组(显示对象数据数组)
		 * @param fps:Number=24 影片帧频
		 * 
		 */		
		public function SimulateMovieClip(datas:Array=null,fps:Number=24)
		{
			super();
			
			init();
			
			this.fps=fps;
			this.datas=datas;
		}
		
		/*
		-----------------------------------
		setters getters
		-----------------------------------
		*/
		//
		/**
		 * 2维帧数组(显示对象数据数组)，每帧数组元素为显示对象或字符串(用BitmapDataEncoder和Base64将BitmapData编码)
		 * @param value:Array
		 * 
		 */		
		public function set datas(value:Array):void{
			setFrames(value);
		}
		//
		/**
		 * 2维帧数组(显示对象数据数组)，每帧数组元素为显示对象或字符串(用BitmapDataEncoder和Base64将BitmapData编码)
		 * @param value:Array
		 * 
		 */			
		public function get datas():Array{
			return _datas;
		}
		//
		/**
		 * 同MovieClip.currentFrame 当前帧 ，不同点:从0开始
		 * @return int
		 * 
		 */		
		public function get currentFrame():int{
			return _currentFrame;
		}
		//
		/**
		 * 同MovieClip.totalFrames 总帧数 
		 * @return int
		 * 
		 */		
		public function get totalFrames():int{
			return _datas.length;
		}
		//
		/**
		 * 当前帧和总帧数比值
		 * @return Number
		 * 
		 */		
		public function get percent():Number{
			return (_currentFrame+1)/_datas.length;
		}
		//
		/**
		 * 影片播放时的帧频 
		 * @param value:uint
		 * 
		 */		
		public function set fps(value:uint):void{
			_fps=value;
			if(_fps<=0)
				_fps=24;
			
			_playTimer.delay=1000/_fps;
		}
		//
		/**
		 * 影片播放时的帧频 
		 * @param value:uint
		 * 
		 */	
		public function get fps():uint{
			return _fps;
		}
		/*
		-----------------------------------
		public  methods
		-----------------------------------
		*/
		//
		/**
		 * 同MovieClip.gotoAndPlay()，不同点:参数可以为百分比，此时跳转至frameOrPercent*totoalFrames 
		 * @param frameOrPercent:Number=0
		 * 
		 */		
		public function gotoAndPlay(frameOrPercent:Number=0):void{
			setCurrentFrame(frameOrPercent);
			
			play();
		}
		//
		/**
		 * 同MovieClip.play() 
		 * 
		 */		
		public function play():void{
			_isPlaying=true;
			
			showFrame();
			startTimer();
		}
		//
		/**
		 * 同MovieClip.gotoAndPlay()，不同点:参数可以为百分比，此时跳转至frameOrPercent*totoalFrames 
		 * @param frameOrPercent:Number=0
		 * 
		 */
		public function gotoAndStop(frameOrPercent:Number=0):void{
			setCurrentFrame(frameOrPercent);
			
			stop();
		}
		//
		/**
		 * 同MovieClip.stop() 
		 * 
		 */
		public function stop():void{
			_isPlaying=false;
			
			showFrame();
			stopTimer();
		}
		//
		/**
		 * 添加1帧到影片最后 
		 * @param data:Array 数组元素为显示对象或字符串(用BitmapDataEncoder和Base64将BitmapData编码)
		 * 
		 */		
		public function addFrame(data:Array):void{
			_datas.push(data);
		}
		//
		/**
		 * 添加1帧到影片指定位置 
		 * @param data:Array 数组元素为显示对象或字符串(用BitmapDataEncoder和Base64将BitmapData编码)
		 * @param frame:int 帧索引，从0开始
		 * 
		 */		
		public function addFrameAt(data:Array,frame:int):void{
			_datas.splice(frame,0,data);
		}
		//
		/**
		 * 添加多帧至影片最后 
		 * @param datas:Array 数组元素为显示对象或字符串(用BitmapDataEncoder和Base64将BitmapData编码)
		 * 
		 */		
		public function addFrames(datas:Array):void{
			_datas=_datas.concat(datas);
		}
		//
		/**
		 * 设置2维帧数组(显示对象数据数组)，数组元素为显示对象或字符串(用BitmapDataEncoder和Base64将BitmapData编码) 
		 * @param datas:Array
		 * 
		 */		
		public function setFrames(datas:Array):void{
			_datas=datas;
			
			showFrame();
		}
		//
		/**
		 * 删除指定帧 
		 * @param frame:int
		 * 
		 */		
		public function removeFrameAt(frame:int):void{
			_datas.splice(frame,1);
			
			showFrame();
		}
		//
		/**
		 * 从索引处删除多帧 
		 * @param frame:int 从0开始的帧索引
		 * @param frameCount:uint 删除帧数
		 * 
		 */		
		public function removeFramesAt(frame:int,frameCount:uint):void{
			_datas.splice(frame,frameCount);
			
			showFrame();
		}
		//
		/**
		 * 销毁对象实例，并释放资源(从显示列表删除，删除所有侦听)
		 * 
		 */	
		public function destroy():void{
			stopTimer();
			removeListeners();
			
			if(this.parent!=null){
				this.parent.removeChild(this);
			}
		}
		/*
		-----------------------------------
		private  methods
		-----------------------------------
		*/
		//初始化
		private function init():void{
			_playTimer=new Timer(1000/_fps);
		}
		//添加侦听
		private function addEventListeners():void{
			this.addEventListener(Event.ADDED_TO_STAGE,thisAddedToStage);
		}
		//删除侦听
		private function removeListeners():void{
			this.removeEventListener(Event.ADDED_TO_STAGE,thisAddedToStage);
		}
		//添加到显示列表
		private function thisAddedToStage(e:Event):void{
			if(_isPlaying)
				startTimer();
		}
		//开始计时器
		private function startTimer():void{
			_playTimer.addEventListener(TimerEvent.TIMER,playTimerTimer);
			_playTimer.start();
		}
		//停止计时器
		private function stopTimer():void{
			_playTimer.stop();
			_playTimer.removeEventListener(TimerEvent.TIMER,playTimerTimer);
		}
		//计时器处理
		private function playTimerTimer(e:TimerEvent):void{
			if(this.stage==null){
				stopTimer();
				return;
			}
			
			if(_datas.length==0){
				stopTimer();
				return;
			}
			
			showFrame();
			
			e.updateAfterEvent();
		}
		//显示当前帧
		private function showFrame():void{
			if(_datas.length==0||_datas[_currentFrame].length==0){
				return;
			}
			
			if(_datas[_currentFrame][0] is String){
				showFrameByBitmap(_currentFrame);
			}else{
				showFrameByDisplayObject(_currentFrame);
			}
			
			if(_isPlaying)
				_currentFrame++;
			if(_currentFrame>_datas.length-1)
				_currentFrame=0;
			
			this.dispatchEvent(new Event(Event.ENTER_FRAME));
		}
		//帧数据为位图数据字符串时显示当前帧
		private function showFrameByBitmap(frame:int):void{
			while(this.numChildren)
				this.removeChildAt(0);
			for(var i:int=0;i<_datas[frame].length;i++){
				var $bitmap:Bitmap=new Bitmap();
				if(_datas[frame][i]!=null){
					var $bmd:BitmapData=BitmapDataEncoder.decodeFromByteArray(Base64.decodeToByteArray(_datas[frame]));
					$bitmap.bitmapData=$bmd;
					this.addChild($bitmap);
				}
			}
			
		}
		//帧数据为显示对象时显示当前帧
		private function showFrameByDisplayObject(frame:int):void{
			while(this.numChildren)
				this.removeChildAt(0);
			
			for(var i:int=0;i<_datas[frame].length;i++){
				if(_datas[frame][i]!=null){
					this.addChild(_datas[frame][i]);
				}
			}
		}
		//设置当前帧
		private function setCurrentFrame(frameOrPercent:Number):void{
			if(_datas.length==0){
				return;
			}
			
			_currentFrame=frameOrPercent;
			if(frameOrPercent<1){
				_currentFrame=Math.floor(frameOrPercent*_datas.length);
			}
			_currentFrame=Math.max(0,_currentFrame);
			_currentFrame=Math.min(_datas.length-1,_currentFrame);
		}
	}
}